﻿using System;
using System.Collections.Generic;
using UnityEngine;

// Token: 0x020002E3 RID: 739
public class TreeSpawner : MonoBehaviour
{
	// Token: 0x0600111E RID: 4382 RVA: 0x0007E9E1 File Offset: 0x0007CBE1
	private void Start()
	{
		this.treePrefabs = Resources.LoadAll<GameObject>("Nature/Tree");
		this.mainCamera = Camera.main.GetComponent<PlayerCamera>();
		this.patchs = new List<TreeSpawner.Patch>();
		this.patchsToFill = new Queue<TreeSpawner.Patch>();
	}

	// Token: 0x0600111F RID: 4383 RVA: 0x0007EA1C File Offset: 0x0007CC1C
	private void PlaceTree(Vector3 position, TreeSpawner.Patch patch)
	{
		Vector3 origin = CenterOrigin.VirtualToWorld(this.highestPoint);
		origin.x = position.x;
		origin.z = position.z;
		RaycastHit raycastHit;
		if (!Physics.Raycast(origin, Vector3.down, out raycastHit, this.highestPoint.y - this.lowestPoint, Layers.walkableMask))
		{
			return;
		}
		if (raycastHit.collider.gameObject.layer != Layers.mapLayer)
		{
			return;
		}
		float num = Vector3.Angle(Vector3.up, raycastHit.normal);
		if (num > 30f)
		{
			return;
		}
		this.SpawnTree(raycastHit.point, patch);
	}

	// Token: 0x06001120 RID: 4384 RVA: 0x0007EACA File Offset: 0x0007CCCA
	private void SpawnTree(Vector3 point, TreeSpawner.Patch patch)
	{
		if (this.totalTreeCount >= this.maxTrees)
		{
			this.PoolTree(point, patch);
		}
		else
		{
			this.CreateTree(point, patch);
		}
	}

	// Token: 0x06001121 RID: 4385 RVA: 0x0007EAF4 File Offset: 0x0007CCF4
	private void PoolTree(Vector3 point, TreeSpawner.Patch patch)
	{
		GameObject treeFromPool = this.GetTreeFromPool();
		if (treeFromPool == null)
		{
			return;
		}
		patch.trees[patch.treeCount] = treeFromPool;
		treeFromPool.transform.position = point;
		patch.treeCount++;
	}

	// Token: 0x06001122 RID: 4386 RVA: 0x0007EB40 File Offset: 0x0007CD40
	private GameObject GetTreeFromPool()
	{
		if (this.poolingPatch == null || this.poolingPatch.treeCount == 0)
		{
			this.PoolPatch();
		}
		if (this.poolingPatch == null || this.poolingPatch.treeCount == 0)
		{
			return null;
		}
		this.poolingPatch.treeCount--;
		GameObject result = this.poolingPatch.trees[this.poolingPatch.treeCount];
		this.poolingPatch.trees[this.poolingPatch.treeCount] = null;
		return result;
	}

	// Token: 0x06001123 RID: 4387 RVA: 0x0007EBD0 File Offset: 0x0007CDD0
	private void PoolPatch()
	{
		if (this.patchs.Count == 0)
		{
			return;
		}
		int index = 0;
		int num = 0;
		for (int i = 0; i < this.patchs.Count; i++)
		{
			TreeSpawner.Patch patch = this.patchs[i];
			int num2 = Mathf.Abs(patch.x - this.patchX) + Mathf.Abs(patch.z - this.patchZ);
			if (num2 > num && !patch.IsVisible())
			{
				index = i;
				num = num2;
			}
		}
		this.poolingPatch = this.patchs[index];
		this.patchs.RemoveAt(index);
		if (this.poolingPatch.treeCount == 0)
		{
			this.PoolPatch();
		}
	}

	// Token: 0x06001124 RID: 4388 RVA: 0x0007EC90 File Offset: 0x0007CE90
	private void CreateTree(Vector3 point, TreeSpawner.Patch patch)
	{
		patch.trees[patch.treeCount] = UnityEngine.Object.Instantiate<GameObject>(this.treePrefabs[UnityEngine.Random.Range(0, this.treePrefabs.Length)], point, Quaternion.identity);
		if (this.editorMode)
		{
			patch.trees[patch.treeCount].transform.SetParent(this.root);
		}
		patch.treeCount++;
		this.totalTreeCount++;
	}

	// Token: 0x06001125 RID: 4389 RVA: 0x0007ED0E File Offset: 0x0007CF0E
	private void Update()
	{
		this.CheckPatch();
		this.FillPatchs();
	}

	// Token: 0x06001126 RID: 4390 RVA: 0x0007ED1C File Offset: 0x0007CF1C
	private void CheckPatch()
	{
		if (this.mainCamera.target == null)
		{
			return;
		}
		Vector3 vector = CenterOrigin.WorldToVirtual(this.mainCamera.target.position);
		int num = (int)Mathf.Floor(vector.x / this.patchSize);
		int num2 = (int)Mathf.Floor(vector.z / this.patchSize);
		if (num != this.patchX || num2 != this.patchZ)
		{
			int num3 = num - this.patchX;
			int num4 = num2 - this.patchZ;
			this.patchX = num;
			this.patchZ = num2;
			this.RenderNeighboors(num + num3 * this.depth, num2 + num4 * this.depth);
		}
	}

	// Token: 0x06001127 RID: 4391 RVA: 0x0007EDD4 File Offset: 0x0007CFD4
	private void FillPatchs()
	{
		if (this.patchsToFill.Count == 0)
		{
			return;
		}
		TreeSpawner.Patch patch = this.patchsToFill.Dequeue();
		this.RenderPatch(patch);
		this.patchs.Add(patch);
	}

	// Token: 0x06001128 RID: 4392 RVA: 0x0007EE14 File Offset: 0x0007D014
	private void RenderNeighboors(int x, int z)
	{
		int num = 4;
		for (int i = -num; i <= num; i++)
		{
			for (int j = -num; j <= num; j++)
			{
				int x2 = x + i;
				int z2 = z + j;
				if (!this.PatchExists(x2, z2))
				{
					TreeSpawner.Patch item = this.CreatePatch(x2, z2);
					this.patchsToFill.Enqueue(item);
				}
			}
		}
	}

	// Token: 0x06001129 RID: 4393 RVA: 0x0007EE78 File Offset: 0x0007D078
	private void RenderPatch(TreeSpawner.Patch patch)
	{
		Vector3 a = CenterOrigin.VirtualToWorld(new Vector3((float)patch.x * this.patchSize, 0f, (float)patch.z * this.patchSize));
		for (int i = 0; i < this.treesPerPatch; i++)
		{
			float x = UnityEngine.Random.Range(0f, this.patchSize);
			float z = UnityEngine.Random.Range(0f, this.patchSize);
			Vector3 b = new Vector3(x, 0f, z);
			Vector3 position = a + b;
			this.PlaceTree(position, patch);
		}
	}

	// Token: 0x0600112A RID: 4394 RVA: 0x0007EF0C File Offset: 0x0007D10C
	private TreeSpawner.Patch CreatePatch(int x, int z)
	{
		return new TreeSpawner.Patch
		{
			x = x,
			z = z,
			trees = new GameObject[this.treesPerPatch],
			treeCount = 0
		};
	}

	// Token: 0x0600112B RID: 4395 RVA: 0x0007EF48 File Offset: 0x0007D148
	private bool PatchExists(int x, int z)
	{
		for (int i = 0; i < this.patchs.Count; i++)
		{
			TreeSpawner.Patch patch = this.patchs[i];
			if (patch.x == x && patch.z == z)
			{
				return true;
			}
		}
		foreach (TreeSpawner.Patch patch2 in this.patchsToFill)
		{
			if (patch2.x == x && patch2.z == z)
			{
				return true;
			}
		}
		return false;
	}

	// Token: 0x04001690 RID: 5776
	private GameObject[] treePrefabs;

	// Token: 0x04001691 RID: 5777
	private PlayerCamera mainCamera;

	// Token: 0x04001692 RID: 5778
	private int maxTrees = 2000;

	// Token: 0x04001693 RID: 5779
	private int totalTreeCount;

	// Token: 0x04001694 RID: 5780
	private int treesPerPatch = 20;

	// Token: 0x04001695 RID: 5781
	private float patchSize = 300f;

	// Token: 0x04001696 RID: 5782
	private int patchX;

	// Token: 0x04001697 RID: 5783
	private int patchZ;

	// Token: 0x04001698 RID: 5784
	private int depth = 3;

	// Token: 0x04001699 RID: 5785
	private List<TreeSpawner.Patch> patchs;

	// Token: 0x0400169A RID: 5786
	private TreeSpawner.Patch poolingPatch;

	// Token: 0x0400169B RID: 5787
	private Queue<TreeSpawner.Patch> patchsToFill;

	// Token: 0x0400169C RID: 5788
	private Vector3 highestPoint = new Vector3(0f, 1000f, 0f);

	// Token: 0x0400169D RID: 5789
	private float lowestPoint = 200f;

	// Token: 0x0400169E RID: 5790
	private Transform root;

	// Token: 0x0400169F RID: 5791
	private bool editorMode;

	// Token: 0x020002E4 RID: 740
	public class Patch
	{
		// Token: 0x0600112D RID: 4397 RVA: 0x0007F004 File Offset: 0x0007D204
		public bool IsVisible()
		{
			if (this.treeCount == 0)
			{
				return false;
			}
			Vector3 vector = Camera.main.WorldToViewportPoint(this.trees[0].transform.position);
			return vector.x >= 0f && vector.x <= 1f && vector.y >= 0f && vector.y <= 1f && vector.z >= 0f;
		}

		// Token: 0x040016A0 RID: 5792
		public int x;

		// Token: 0x040016A1 RID: 5793
		public int z;

		// Token: 0x040016A2 RID: 5794
		public GameObject[] trees;

		// Token: 0x040016A3 RID: 5795
		public int treeCount;
	}
}
